import net.java.games.jogl.*;
import net.java.games.jogl.util.GLUT;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;
import java.awt.Dimension;
import java.lang.Math.*;
import java.util.Vector;
import java.util.Collections;
import java.lang.Comparable;

public class opengl implements GLEventListener, MouseListener, MouseMotionListener
{
    private int prevMouseX, prevMouseY;
    private boolean mouseRButtonDown = false;
    private GLUT glut;
    private float translateX = 0.0f, translateY = 0.0f, translateZ = -21.0f;
    private model3d box, sphere, cross;
    private float judgeText, judgeTextY,judgeScreenPosX[], judgeScreenPosY[];

    public double PI() {
        return 3.14159265359; // value of pi
    }

    public double DEG2RAD(double val) {
        return (3.14159265359 / 180 * val);
    }

    public double RAD2DEG(double val) {
        return (180 / 3.14159265359 * val);
    }

    public opengl() {

    }

    public void init(GLDrawable drawable) {
        drawable.addMouseListener(this);
        drawable.addMouseMotionListener(this);

        glut = new GLUT();

        GL gl = drawable.getGL();

        //specify clear color to black
        gl.glClearColor(0, 0, 0, 0);

        //smooth shading
        gl.glShadeModel(gl.GL_SMOOTH);

        //auto normalize all the vectors
        gl.glEnable(GL.GL_NORMALIZE);

        //light setup
        float pos[] = {0.0f, 0.0f, 1.0f, 0.0f};

        //enable lighting
        gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, pos);
        gl.glEnable(GL.GL_LIGHTING);
        gl.glEnable(GL.GL_LIGHT0);

        //enable depth testing
        gl.glEnable(GL.GL_DEPTH_TEST);

        //enable color material
        gl.glEnable(gl.GL_COLOR_MATERIAL);
        gl.glColorMaterial(gl.GL_FRONT, gl.GL_AMBIENT_AND_DIFFUSE);

        // hard-coded number of judges
        judgeScreenPosX = new float[10];
        judgeScreenPosY=new float[10]; 
        
        box = new model3d();
        box.read("models/boxMod.txt");
        box.update(gl);

        sphere = new model3d();
        sphere.read("models/sphereMod.txt");
        sphere.update(gl);

        cross = new model3d();
        cross.read("models/crossMod.txt");
        cross.update(gl);
        
        judgeText = 780;
        judgeTextY = 725;
        
        resetJudgingScreen();

    }

    void printText(GL gl, int font, String string, float x, float y, float z, float scale) {
        gl.glPushMatrix();

        gl.glTranslatef(x, y, z);
        gl.glNormal3f(0, 0, 1);
        gl.glRasterPos2i(0, 0);
        gl.glScaled(scale, -scale, 1.0);
        glut.glutStrokeString(gl, font, string);
        gl.glPopMatrix();
    }


    void setOrthoProjection(GL gl, int width, int height) {
        gl.glMatrixMode(gl.GL_PROJECTION);
        gl.glLoadIdentity();
        //gl.glOrtho(0, width, height,0, 1, 100);
        gl.glOrtho(0, 1024, 768, 0, 1, 100);
        gl.glMatrixMode(gl.GL_MODELVIEW);
        gl.glLoadIdentity();

    }

    void setPresProjection(GL gl, int width, int height) {
        gl.glMatrixMode(gl.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glFrustum(0, width, height, 0, 1, 100);
        gl.glMatrixMode(gl.GL_MODELVIEW);
        gl.glLoadIdentity();
    }

    public void reshape(GLDrawable drawable, int x, int y, int width,
                        int height) {
        GL gl = drawable.getGL();
        GLU glu = drawable.getGLU();
        setOrthoProjection(gl, width, height);
    }
    
    //resets screen for specific judges
    public void resetJudgingScreen()
    {
        //if variables not init return
        if(judgeScreenPosX==null || judgeScreenPosY==null)
            return;
        
        //first 3 for judge A
        //second 3 for judge B
        //last 3 for judge C
        if(globalData.scoringSystem==0)
        {
            judgeScreenPosX[0]=25;
            judgeScreenPosX[1]=450;
            judgeScreenPosX[2]=800;
            judgeScreenPosX[3]=25;
            judgeScreenPosX[4]=450;
            judgeScreenPosX[5]=800;
            judgeScreenPosX[6]=25;
            judgeScreenPosX[7]=450;
            judgeScreenPosX[8]=800;
            judgeScreenPosX[9]=450;
            
            judgeScreenPosY[0] = 333;
            judgeScreenPosY[1] = 333;
            judgeScreenPosY[2] = 333;
            judgeScreenPosY[3] = 466;
            judgeScreenPosY[4] = 466;
            judgeScreenPosY[5] = 466;
            judgeScreenPosY[6] = 600;
            judgeScreenPosY[7] = 600;
            judgeScreenPosY[8] = 600;
            judgeScreenPosY[9] = 200;
        }
        else if(globalData.scoringSystem==1)
        {
            //y coordiante
            judgeScreenPosY[0]=150;
            judgeScreenPosY[1]=judgeScreenPosY[0]+50;
            judgeScreenPosY[2]=judgeScreenPosY[0]+100;
            judgeScreenPosY[6]=judgeScreenPosY[0]+150;
            judgeScreenPosY[7]=judgeScreenPosY[0]+200;
            
            
            judgeScreenPosY[3] = 475;
            judgeScreenPosY[4] = 475;
            judgeScreenPosY[5] = 550;
            judgeScreenPosY[8]=  550;
            judgeScreenPosY[9] = 625;
                        
            //x coordinates
            judgeScreenPosX[3]=25;
            judgeScreenPosX[4]=judgeScreenPosX[3]+250;
            judgeScreenPosX[5] = judgeScreenPosX[3];
            judgeScreenPosX[8] = judgeScreenPosX[3] + 250;
            judgeScreenPosX[9] = judgeScreenPosX[3];
        }
        else
        {
            //y coordiante
            judgeScreenPosY[0]=150;
            judgeScreenPosY[1]=judgeScreenPosY[0]+50;
            judgeScreenPosY[2]=judgeScreenPosY[0]+100;

            judgeScreenPosY[6]=judgeScreenPosY[0]+250;
            judgeScreenPosY[7]= judgeScreenPosY[6]+50;
            judgeScreenPosY[8]= judgeScreenPosY[6]+100;

            //x coordinates
            judgeScreenPosY[3] = 675;
            judgeScreenPosY[4] = 675;
            judgeScreenPosY[5] = 750;
            judgeScreenPosY[9] = 750;
            
            judgeScreenPosX[3]=25;
            judgeScreenPosX[4]=judgeScreenPosX[3]+250;
            judgeScreenPosX[5] = judgeScreenPosX[3];
            judgeScreenPosX[9] = judgeScreenPosX[3] + 250;
        }
       
    }

    private void showScreenInfo(GL gl) {
        
        //first 3 for judge A
        //second 3 for judge B
        //last 3 for judge C
        if(globalData.scoringSystem==0)
        {
            //show Nandu
            gl.glColor3f(0, 0, 1);
            gl.glPushMatrix();
            gl.glNormal3f(0, 0, 1);
            gl.glRasterPos2i(0, 0);
            gl.glTranslatef(512 -
                            (glut.glutStrokeLength(glut.STROKE_ROMAN, "SCORES") / 4),
                            100, translateZ);
            gl.glScaled(0.5, -0.5, 1.0);
            glut.glutStrokeString(gl, glut.STROKE_ROMAN, "SCORES");
            gl.glPopMatrix();            
        }
        else if(globalData.scoringSystem==1)
        {
            //show mistakes
            gl.glColor3f(0, 0, 1);
            gl.glPushMatrix();
                gl.glNormal3f(0, 0, 1);
                gl.glRasterPos2i(0, 0);
                gl.glTranslatef(512 -
                                (glut.glutStrokeLength(glut.STROKE_ROMAN, "MISTAKES") / 4),
                                judgeScreenPosY[0] - 50, translateZ);
                gl.glScaled(0.5, -0.5, 1.0);
                glut.glutStrokeString(gl, glut.STROKE_ROMAN, "MISTAKES");
            gl.glPopMatrix();

            //show scores
            gl.glColor3f(0, 0, 1);
            gl.glPushMatrix();
                gl.glNormal3f(0, 0, 1);
                gl.glRasterPos2i(0, 0);
                gl.glTranslatef(512 -
                                (glut.glutStrokeLength(glut.STROKE_ROMAN, "SCORES") / 4),
                                judgeScreenPosY[3] -50, translateZ);
                gl.glScaled(0.5, -0.5, 1.0);
                glut.glutStrokeString(gl, glut.STROKE_ROMAN, "SCORES");
            gl.glPopMatrix();          
        }
        else
        {
            //show mistakes
            gl.glColor3f(0, 0, 1);
            gl.glPushMatrix();
            gl.glNormal3f(0, 0, 1);
            gl.glRasterPos2i(0, 0);
            gl.glTranslatef(512 -
                            (glut.glutStrokeLength(glut.STROKE_ROMAN, "MISTAKES") / 4),
                            judgeScreenPosY[0] - 50, translateZ);
            gl.glScaled(0.5, -0.5, 1.0);
            glut.glutStrokeString(gl, glut.STROKE_ROMAN, "MISTAKES");
            gl.glPopMatrix();

            //show nandu
            gl.glColor3f(0, 0, 1);
            gl.glPushMatrix();
            gl.glNormal3f(0, 0, 1);
            gl.glRasterPos2i(0, 0);
            gl.glTranslatef(512 -
                            (glut.glutStrokeLength(glut.STROKE_ROMAN, "NANDU") /
                             4), judgeScreenPosY[6] - 50, translateZ);
            gl.glScaled(0.5, -0.5, 1.0);
            glut.glutStrokeString(gl, glut.STROKE_ROMAN, "NANDU");
            gl.glPopMatrix();

            //show scores
            gl.glColor3f(0, 0, 1);
            gl.glPushMatrix();
            gl.glNormal3f(0, 0, 1);
            gl.glRasterPos2i(0, 0);
            gl.glTranslatef(512 -
                            (glut.glutStrokeLength(glut.STROKE_ROMAN, "SCORES") / 4),
                            judgeScreenPosY[8] + 100, translateZ);
            gl.glScaled(0.5, -0.5, 1.0);
            glut.glutStrokeString(gl, glut.STROKE_ROMAN, "SCORES");
            gl.glPopMatrix();
        }
       
    }

    private void drawTimeLine(GL gl, float y)
    {
        int constMult=100;
        int maxTime=3;//minutes
        gl.glBegin(gl.GL_LINES);
           gl.glColor3f(.5f,.5f,.5f);
           gl.glVertex2f(0,y);
           gl.glVertex2f(maxTime*60*constMult,y);
           for(int x=maxTime*60*constMult;x>=0;x-=60*constMult)
           {
               gl.glVertex2f(x,y-15);
               gl.glVertex2f(x,y+15+1);
           }

           for(int x=maxTime*60*constMult;x>=0;x-=30*constMult)
           {
               gl.glVertex2f(x,y-10);
               gl.glVertex2f(x,y);
           }

           for(int x=maxTime*60*constMult;x>=0;x-=10*constMult)
           {
               gl.glVertex2f(x,y-5);
               gl.glVertex2f(x,y);
           }


       gl.glEnd();


    }

    public static long getMinutes(long milliseconds)
    {
        return milliseconds / (60 * 1000); // 60 s/min * 1000 ms/s
    }
    
    public static long getSeconds(long milliseconds)
    {
        return (milliseconds % (60 * 1000)) / 1000;
    }
    
    // check whether the A Judge's data is ready for finalizing
    // TODO: this is a hack.  the best thing is to use a "finalized" flag for the judges
    public boolean isFinalizedA(Vector data)
    {
        for (int i = 0; i < data.size(); i++)
        {
            if (((point)data.elementAt(i)).y < 0) {
                return false;
            }
        }
        
        return true;
    }
    
    public void display(GLDrawable drawable)
    {
        int i,j;
        point p;
        
        GL gl = drawable.getGL();
        GLU glu = drawable.getGLU();
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

        globalData.setLock();
        
            gl.glLoadIdentity();
            showScreenInfo(gl);
            //activate time only when active player is around
            if(globalData.athleteActive)
            {
                globalData.getTime();
            }

            //show time
            gl.glColor3f(1,0,0);

            String time="T "+ getMinutes(globalData.diffTime) + ":" + String.format("%02d", getSeconds(globalData.diffTime));
            //shows current time
            printText(gl, GLUT.STROKE_ROMAN, time,800,75,-1, .5f);


            //first 3 for judge A
            //second 3 for judge B
            //last 3 for judge C
            if(globalData.scoringSystem==0)
            {
                //show all judge of type B
                gl.glColor3f(1,1,1);

                if (globalData.currentAthlete != null) 
                {
                    for(j=0;j<(globalData.totalJudges-1);j++)
                    {
                        i=globalData.currentAthlete.getJudgeVector(j).size()-1;
                        if(i>=0)
                        {
                            p=(point)globalData.currentAthlete.getJudgeVector(j).elementAt(i);
                            //y value is ignore in judge C
                            printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", p.x),judgeScreenPosX[j],judgeScreenPosY[j],-1,0.50f);
                        }
                    }            
                    i=globalData.currentAthlete.getJudgeVector(j).size();
                    // Print Head Judge's score
                    if(i >= 1)
                    {
                        Double score = (Double) globalData.currentAthlete.getJudgeVector(j).firstElement();
                        //y value is ignore in judge C
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", score),judgeScreenPosX[j],judgeScreenPosY[j],-1,0.50f);
                    }
                    // Print deductions
                    if (i >= 2)
                    {
                        Double deduction = globalData.currentAthlete.calculateDeductions();
                        gl.glColor3f(1,0,0);
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", deduction), judgeText-300, judgeTextY, -1, 0.50f);
                    }

                    if(globalData.currentAthlete.hasCompeted() && globalData.displayScore)
                    {
                        gl.glColor3f(0.2f,1,0.2f);
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", globalData.currentAthlete.calculateFinalScore(globalData.scoringSystem)), judgeText, judgeTextY, -1, 0.75f);
    //                   // String scoreA=globalData.currentAthlete.getAScore();
                        String scoreB=globalData.currentAthlete.getBScore();
    //                   // String scoreC=globalData.currentAthlete.getCScore();
    //                    gl.glColor3f(0.2f,.5f,0.2f);
    //                   // printText(gl, GLUT.STROKE_ROMAN, scoreA, judgeText, judgeTextY+40, -1, 0.25f);
                        printText(gl, GLUT.STROKE_ROMAN, scoreB, judgeText+80, judgeTextY+40, -1, 0.25f);
    //                   // printText(gl, GLUT.STROKE_ROMAN, scoreC, judgeText+160, judgeTextY+40, -1, 0.25f);

                    }
                    gl.glColor3f(1,1,1);
                }

            }
            else if(globalData.scoringSystem==1)
            {
                //show all judge of type B
                gl.glColor3f(1,1,1);
                for(j=0;globalData.currentAthlete!=null && j<(globalData.totalJudges-1);j++)
                {
                    //converts judges index to appopriate type
                    if(globalData.judgeIndexToJudgeType(j)!=judge.judgeType.judgeB)
                         continue;
                    i=globalData.currentAthlete.getJudgeVector(j).size()-1;
                    if(i>=0)
                    {
                        p=(point)globalData.currentAthlete.getJudgeVector(j).elementAt(i);
                        //y value is ignore in judge C
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", p.x),judgeScreenPosX[j],judgeScreenPosY[j],-1,0.50f);
                    }
                }
                //for head judge
                j = (globalData.totalJudges-1);
                if (globalData.currentAthlete != null) {
                    i=globalData.currentAthlete.getJudgeVector(j).size();
                    // Print Head Judge's score
                    if(i >= 1)
                    {
                        Double score = (Double) globalData.currentAthlete.getJudgeVector(j).firstElement();
                        //y value is ignore in judge C
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", score),judgeScreenPosX[j],judgeScreenPosY[j],-1,0.50f);
                    }
                    // Print deductions
                    if (i >= 2)
                    {
                        Double deduction = globalData.currentAthlete.calculateDeductions();
                        gl.glColor3f(1,0,0);
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", deduction), judgeText-300, judgeTextY, -1, 0.50f);
                    }

                    if(globalData.currentAthlete.hasCompeted() && globalData.displayScore)
                    {
                        gl.glColor3f(0.2f,1,0.2f);
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", globalData.currentAthlete.calculateFinalScore(globalData.scoringSystem)), judgeText, judgeTextY, -1, 0.75f);
                        String scoreA=globalData.currentAthlete.getAScore();
                        String scoreB=globalData.currentAthlete.getBScore();
                        //String scoreC=globalData.currentAthlete.getCScore();
                        gl.glColor3f(0.2f,.5f,0.2f);
                        printText(gl, GLUT.STROKE_ROMAN, scoreA, judgeText, judgeTextY+40, -1, 0.25f);
                        printText(gl, GLUT.STROKE_ROMAN, scoreB, judgeText+80, judgeTextY+40, -1, 0.25f);
                        //printText(gl, GLUT.STROKE_ROMAN, scoreC, judgeText+160, judgeTextY+40, -1, 0.25f);
                    }
                    gl.glColor3f(1,1,1);
                }

                 gl.glTranslatef(translateX, translateY , translateZ);

                //draw lines
                for(i=0;i<(globalData.totalJudges-1);i++)
                {
                    if(globalData.currentAthlete!=null && (globalData.judgeIndexToJudgeType(i)==judge.judgeType.judgeA || globalData.judgeIndexToJudgeType(i)==judge.judgeType.judgeC))
                    {
                        drawTimeLine(gl,judgeScreenPosY[i]);
                    }
                }
                //show all judge of type A
                Vector unfinalizedA = new Vector();
                Vector finalizedA = new Vector();

                for(j=0;globalData.currentAthlete!=null && j<(globalData.totalJudges-1);j++)
                {
                     if(globalData.judgeIndexToJudgeType(j)!=judge.judgeType.judgeA)
                         continue;
                     Vector data=globalData.currentAthlete.getJudgeVector(j);
                     if (!isFinalizedA(data)) {
                         unfinalizedA.addElement(new athlete.Deduction(j,data));
                     }
                     else {
                         finalizedA.addElement(new athlete.Deduction(j,data));
                     }
                }
                // render and retrieve unfinalized deductions
                if (unfinalizedA.size() > 0) {
                    Vector unfinal_deductions = athlete.computeADeductions(unfinalizedA,globalData.currentAthlete.getJudgeATimeRangeInSec());

                    int b;
                    for (b = 0; b < unfinal_deductions.size(); b++)
                    {
                        Vector bin = (Vector) unfinal_deductions.elementAt(b);
                        int ju;
                        for (ju = 0; ju < bin.size(); ju++)
                        {
                            //int new_x = 50 + (int) b * 900 / (final_deductions.size());
                            int new_x = 50 + b * 60;
                            athlete.DeductPoint deduction = (athlete.DeductPoint) bin.elementAt(ju);

                            gl.glColor3f(0, 1, 0);
                            sphere.show(gl, new_x, judgeScreenPosY[deduction.judgeIndex], -1);
                        }
                    }            
                }
                // retrieve and render finalized deductions
                if (finalizedA.size() > 0) {
                    Vector final_deductions = athlete.computeADeductions(finalizedA,globalData.currentAthlete.getJudgeATimeRangeInSec());

                    int numJudgeA=0;
                    int ii;
                    for (ii = 0; ii < (globalData.totalJudges-1); ii++)
                    {
                        if(globalData.currentAthlete.getJudgeType(ii)==judge.judgeType.judgeA)
                        {
                            if(globalData.currentAthlete.getJudgeConnected(ii)==true)
                                numJudgeA++;
                        }
                    }

                    int b;
                    for (b = 0; b < final_deductions.size(); b++)
                    {
                        Vector bin = (Vector) final_deductions.elementAt(b);
                        int ju;
                        for (ju = 0; ju < bin.size(); ju++)
                        {
                            //int new_x = 50 + (int) b * 900 / (final_deductions.size());
                            int new_x = 50 + b * 60;
                            athlete.DeductPoint deduction = (athlete.DeductPoint) bin.elementAt(ju);

                            //cross.show(gl,new_x,judgeScreenPos[ju],0);
                            if (bin.size() > 1 || numJudgeA==1) { // more than one judge agrees
                                gl.glColor3f(1, 0, 0);
                            }
                            else {
                                gl.glColor3f(0, 0, 1);
                            }
                            sphere.show(gl, new_x, judgeScreenPosY[deduction.judgeIndex], -1);
                            String value = String.format("%02d", deduction.code);
                            gl.glColor3f(1, 1, 1);
                            printText(gl, GLUT.STROKE_ROMAN, value,
                             new_x - (glut.glutStrokeLength(glut.STROKE_ROMAN, "00") / 8),
                             judgeScreenPosY[deduction.judgeIndex] + 15, 20, .25f);
                        }
                    }
                }

            }
            else
            {

                //show all judge of type B
                gl.glColor3f(1,1,1);
                for(j=0;globalData.currentAthlete!=null && j<(globalData.totalJudges-1);j++)
                {
                     if(globalData.currentAthlete.getJudgeType(j)!=judge.judgeType.judgeB)
                         continue;
                    i=globalData.currentAthlete.getJudgeVector(j).size()-1;
                    if(i>=0)
                    {
                        p=(point)globalData.currentAthlete.getJudgeVector(j).elementAt(i);
                        //y value is ignore in judge C
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", p.x),judgeScreenPosX[j],judgeScreenPosY[j],-1,0.50f);
                    }
                }
                //for head judge
                j = (globalData.totalJudges-1);
                if (globalData.currentAthlete != null) {
                    i=globalData.currentAthlete.getJudgeVector(j).size();
                    // Print Head Judge's score
                    if(i >= 1)
                    {
                        Double score = (Double) globalData.currentAthlete.getJudgeVector(j).firstElement();
                        //y value is ignore in judge C
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", score),judgeScreenPosX[j],judgeScreenPosY[j],-1,0.50f);
                    }
                    // Print deductions
                    if (i >= 2)
                    {
                        Double deduction = globalData.currentAthlete.calculateDeductions();
                        gl.glColor3f(1,0,0);
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", deduction), judgeText-300, judgeTextY, -1, 0.50f);
                    }

                    if(globalData.currentAthlete.hasCompeted() && globalData.displayScore)
                    {
                        gl.glColor3f(0.2f,1,0.2f);
                        printText(gl, GLUT.STROKE_ROMAN, String.format("%.2f", globalData.currentAthlete.calculateFinalScore(globalData.scoringSystem)), judgeText, judgeTextY, -1, 0.75f);
                        String scoreA=globalData.currentAthlete.getAScore();
                        String scoreB=globalData.currentAthlete.getBScore();
                        String scoreC=globalData.currentAthlete.getCScore();
                        gl.glColor3f(0.2f,.5f,0.2f);
                        printText(gl, GLUT.STROKE_ROMAN, scoreA, judgeText, judgeTextY+40, -1, 0.25f);
                        printText(gl, GLUT.STROKE_ROMAN, scoreB, judgeText+80, judgeTextY+40, -1, 0.25f);
                        printText(gl, GLUT.STROKE_ROMAN, scoreC, judgeText+160, judgeTextY+40, -1, 0.25f);
                    }
                    gl.glColor3f(1,1,1);
                }


                gl.glTranslatef(translateX, translateY , translateZ);

                //draw lines
                for(i=0;i<(globalData.totalJudges-1);i++)
                {
                    if(globalData.currentAthlete!=null && (globalData.currentAthlete.getJudgeType(i)==judge.judgeType.judgeA || globalData.currentAthlete.getJudgeType(i)==judge.judgeType.judgeC))
                    {
                        drawTimeLine(gl,judgeScreenPosY[i]);
                    }
                }
                
                //show all judge of type A
                if(!globalData.displayScore)    //if display scoring is disabled
                {
                    for(j=0;globalData.currentAthlete!=null && j<(globalData.totalJudges-1);j++)
                    {
                         if(globalData.currentAthlete.getJudgeType(j)!=judge.judgeType.judgeA)
                             continue;
                         Vector data=globalData.currentAthlete.getJudgeVector(j);
                         for (int b = 0; b < data.size(); b++)
                         {
                            gl.glColor3f(0, 0, 1);
                            point poi=(point)data.elementAt(b);
                            int new_x=50 + b * 60;
                            sphere.show(gl, new_x, judgeScreenPosY[j], -1);
                            int currCode=(int) poi.y;
                            if(currCode>=0)
                            {
                                String value = String.format("%02d", currCode);
                                gl.glColor3f(1, 1, 1);
                                printText(gl, GLUT.STROKE_ROMAN, value,
                                        new_x - (glut.glutStrokeLength(glut.STROKE_ROMAN, "00") / 8),
                                        judgeScreenPosY[j] + 15, 20, .25f);
                            }
                         }
                    }                
                }
                else
                {
                    Vector unfinalizedA = new Vector();
                    Vector finalizedA = new Vector();

                    for(j=0;globalData.currentAthlete!=null && j<(globalData.totalJudges-1);j++)
                    {
                         if(globalData.currentAthlete.getJudgeType(j)!=judge.judgeType.judgeA)
                             continue;
                         Vector data=globalData.currentAthlete.getJudgeVector(j);
                         if (!isFinalizedA(data)) {
                             unfinalizedA.addElement(new athlete.Deduction(j,data));
                         }
                         else {
                             finalizedA.addElement(new athlete.Deduction(j,data));
                         }
                    }
                    // render and retrieve unfinalized deductions
                    if (unfinalizedA.size() > 0) {
                        Vector unfinal_deductions = athlete.computeADeductions(unfinalizedA,globalData.currentAthlete.getJudgeATimeRangeInSec());

                        int b;
                        for (b = 0; b < unfinal_deductions.size(); b++)
                        {
                            Vector bin = (Vector) unfinal_deductions.elementAt(b);
                            int ju;
                            for (ju = 0; ju < bin.size(); ju++)
                            {
                                //int new_x = 50 + (int) b * 900 / (final_deductions.size());
                                int new_x=50 + b * 60;

                                athlete.DeductPoint deduction = (athlete.DeductPoint) bin.elementAt(ju);

                                gl.glColor3f(0, 1, 0);
                                sphere.show(gl, new_x, judgeScreenPosY[deduction.judgeIndex], -1);
                            }
                        }            
                    }
                    // retrieve and render finalized deductions
                    if (finalizedA.size() > 0) {
                        Vector final_deductions = athlete.computeADeductions(finalizedA,globalData.currentAthlete.getJudgeATimeRangeInSec());

                        int numJudgeA=0;
                        int ii;
                        for (ii = 0; ii < (globalData.totalJudges-1); ii++)
                        {
                            if(globalData.currentAthlete.getJudgeType(ii)==judge.judgeType.judgeA)
                            {
                                if(globalData.currentAthlete.getJudgeConnected(ii)==true)
                                    numJudgeA++;
                            }
                        }

                        int b;
                        for (b = 0; b < final_deductions.size(); b++)
                        {
                            Vector bin = (Vector) final_deductions.elementAt(b);
                            int ju;
                            for (ju = 0; ju < bin.size(); ju++)
                            {
                                //int new_x = 50 + (int) b * 900 / (final_deductions.size());
                                int new_x = 50 + b * 60;
                                athlete.DeductPoint deduction = (athlete.DeductPoint) bin.elementAt(ju);

                                //cross.show(gl,new_x,judgeScreenPos[ju],0);
                                if (bin.size() > 1 || numJudgeA==1) { // more than one judge agrees
                                    gl.glColor3f(1, 0, 0);
                                }
                                else {
                                    gl.glColor3f(0, 0, 1);
                                }
                                sphere.show(gl, new_x, judgeScreenPosY[deduction.judgeIndex], -1);
                                String value = String.format("%02d", deduction.code);
                                gl.glColor3f(1, 1, 1);
                                printText(gl, GLUT.STROKE_ROMAN, value,
                                 new_x - (glut.glutStrokeLength(glut.STROKE_ROMAN, "00") / 8),
                                 judgeScreenPosY[deduction.judgeIndex] + 15, 20, .25f);
                            }
                        }
                    }
                }

                //show all judge of type C
                for(j=0; globalData.currentAthlete!=null && j<(globalData.totalJudges-1);j++)
                {
                    if(globalData.currentAthlete.getJudgeType(j)!=judge.judgeType.judgeC)
                         continue;
                    Vector data=globalData.currentAthlete.getJudgeVector(j);
                    for(i=0;i<data.size();i++)
                    {
                        p=(point)data.elementAt(i);
                        if(p.y==1)  //did athlete hit difficulty
                            gl.glColor3f(0,1,0);
                        else
                            gl.glColor3f(1,0,0);
                        sphere.show(gl,p.x,judgeScreenPosY[j],0);
                    }

                }
            }
        globalData.releaseLock();
     
    }

    public void displayChanged(GLDrawable drawable, boolean modeChanged, boolean deviceChanged)
    {
    }

    //mouse enterd the canvas
    public void mouseEntered(MouseEvent e)
    {
    }

    //mouse existed teh canvas
    public void mouseExited(MouseEvent e)
    {
    }

    //mouse is pressed
    public void mousePressed(MouseEvent e)
    {
        prevMouseX = e.getX();
        prevMouseY = e.getY();
        if ((e.getModifiers() & e.BUTTON3_MASK) != 0)
        {
            mouseRButtonDown = true;
        }
    }

    //mouse is released
    public void mouseReleased(MouseEvent e)
    {
        if ((e.getModifiers() & e.BUTTON3_MASK) != 0)
        {
            mouseRButtonDown = false;
        }
    }

    public void mouseClicked(MouseEvent e)
    {
    }

    // Methods required for the implementation of MouseMotionListener
    public void mouseDragged(MouseEvent e)
    {
        int x = e.getX();
        int y = e.getY();
        Dimension size = e.getComponent().getSize();

        translateX+= (float) (x - prevMouseX);
        if(translateX>0)
            translateX=0;

        prevMouseX = x;
        prevMouseY = y;

    }

    //mouse is moved
    public void mouseMoved(MouseEvent e)
    {

    }

    public void drawSquare(GL gl, float x, float y,float z)
    {
        gl.glPushMatrix();
            gl.glTranslatef(x, y, z);
            gl.glBegin(gl.GL_POLYGON);
                gl.glNormal3f(0, 0, 1);
                gl.glVertex3f(- 50, - 50, 0);
                gl.glVertex3f(+ 50, - 50, 0);
                gl.glVertex3f(+ 50, + 50, 0);
                gl.glVertex3f(- 50, + 50, 0);
            gl.glEnd();
        gl.glPopMatrix();
    }

    public void drawSphere(GL gl, float x, float y,float z, float radius)
    {
        gl.glPushMatrix();
            gl.glTranslatef(x, y, z);
            drawSquare(gl,  0, 0, 0);
       gl.glPopMatrix();

    }

}
